/**
 * 
 */
package com.jolestar.yayaweibotong.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import twitter4j.Paging;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.User;
import twitter4j.http.AccessToken;

import com.jolestar.yayaweibotong.ApiReachLimitException;
import com.jolestar.yayaweibotong.NetworkException;
import com.jolestar.yayaweibotong.ServiceType;
import com.jolestar.yayaweibotong.YayaException;
import com.jolestar.yayaweibotong.dao.AccountDomain;
import com.jolestar.yayaweibotong.dao.RetweetDomain;
import com.jolestar.yayaweibotong.dao.StatusDomain;

/**
 * @author jolestar@gmail.com
 * 
 */
public class TwitterStatusService extends AbstractStatusService<Twitter> {

	TwitterFactory factory = new TwitterFactory();

	/**
	 * 
	 */
	public TwitterStatusService() {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.jolestar.yayaweibotong.service.StatusService#getLatestStatuses(com
	 * .jolestar.yayaweibotong.dao.AccountDomain, long)
	 */
	@Override
	public List<StatusDomain> getLatestStatuses(AccountDomain account,
			String sinceId) {
		Twitter twitter = this.getOrCreateInstance(account);
		Paging page = new Paging();
		if (sinceId != null&&this.existsStatus(ServiceType.twitter, sinceId)) {
			page.setSinceId(Long.parseLong(sinceId));
			page.setCount(5);
		}else{
			page.setCount(1);
		}
		try {
			List<Status> statuses = twitter.getUserTimeline(page);
			if (statuses == null || statuses.isEmpty()) {
				return Collections.emptyList();
			}
			List<StatusDomain> results = new ArrayList<StatusDomain>(
					statuses.size());
			for (Status status : statuses) {
				StatusDomain statusDomain = this.getStatusDomain(ServiceType.twitter, Long.toString(status.getId()));
				if(statusDomain == null){
					statusDomain = this.convert(status, account);
					statusDomain.save();
				}
				results.add(statusDomain);
			}
			return results;
		} catch (TwitterException e) {
			if (e.isCausedByNetworkIssue()) {
				throw new NetworkException(e);
			}
			if(e.exceededRateLimitation()){
				throw new ApiReachLimitException(e);
			}
			throw new YayaException(e);
		}
	}

	private StatusDomain convert(Status status, AccountDomain account) {
		StatusDomain statusDomain = new StatusDomain(ServiceType.twitter,
				Long.toString(status.getId()), account);
		statusDomain.setText(status.getText());
		if (status.isRetweet()) {
			Status rtDetails = status.getRetweetedStatus();
			statusDomain.setRetweet(new RetweetDomain(ServiceType.twitter,
					statusDomain, rtDetails.getId(), rtDetails.getUser()
							.getName(), rtDetails.getUser().getScreenName(),
					rtDetails.getText()));
		}
		statusDomain.setCreateAt(status.getCreatedAt());
		return statusDomain;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.jolestar.yayaweibotong.service.StatusService#updateAccount(com.jolestar
	 * .yayaweibotong.dao.AccountDomain)
	 */
	@Override
	public void updateAccount(AccountDomain account) {
		Twitter twitter = this.getOrCreateInstance(account);
		try {
			User user = twitter.showUser(Integer.parseInt(account
					.getOriginalId()));
			account.setProfileImage(user.getProfileImageURL().toExternalForm());
			account.setDomain(user.getScreenName());
			account.setCreateAt(user.getCreatedAt());
			account.setScreenName(user.getScreenName());
			account.setName(user.getName());
			account.save();
		} catch (TwitterException e) {
			throw new YayaException(e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.jolestar.yayaweibotong.service.StatusService#updateStatus(com.jolestar
	 * .yayaweibotong.dao.AccountDomain,
	 * com.jolestar.yayaweibotong.dao.StatusDomain)
	 */
	@Override
	public StatusDomain updateStatus(AccountDomain account, StatusDomain status) {
		Twitter twitter = this.getOrCreateInstance(account);
		try {
			Status newStatus = twitter.updateStatus(status
					.formatStatus(ServiceType.twitter.getStatusLengthLimit()));
			StatusDomain result = this.convert(newStatus, account);
			result.setSynced(true);
			result.setSyncedAt(new Date());
			result.setOriginalStatus(status);
			result.save();
			return result;
		} catch (TwitterException e) {
			if (e.isCausedByNetworkIssue()) {
				throw new NetworkException(e);
			}
			if(e.exceededRateLimitation()){
				throw new ApiReachLimitException(e);
			}
			throw new YayaException(e);
		}
	}

	@Override
	protected Twitter createInstance(AccountDomain account) {
		Twitter twitter = this.factory.getOAuthAuthorizedInstance(
				ServiceType.twitter.getApiKey(),
				ServiceType.twitter.getApiSecret(),
				new AccessToken(account.getToken(), account.getTokenSecret()));
		return twitter;
	}

}
